package it.eng.area118.mdocommon.android.activity;

import it.eng.area118.mdocommon.UI;
import it.eng.area118.mdocommon.android.log.BasicLogger;
import it.eng.area118.mdocommon.android.model.AndroidModelContainer;
import it.eng.area118.mdocommon.android.notification.FinishEvent;
import it.eng.area118.mdocommon.android.util.AndroidApplicationContext;

import java.io.Serializable;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

/**
 * 
 * @author Luigi
 * 
 */
public abstract class ChildActivity extends Activity implements UI {

	public static final String TAG = "ChildActivity";

	protected boolean isInFront;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		init();
		onStarted();
		registerListerners();
		initFinishListener();
	}

	protected abstract void unregisterListeners();

	protected abstract void registerListerners();

	protected abstract void checkModels();

	@Override
	protected void onStop() {
		unregisterListeners();
		onUnvisible();
		super.onStop();
	}

	private void initFinishListener() {
		AndroidApplicationContext.getInstance().addObserverToContextObs(
				new Observer() {

					@Override
					public void update(Observable arg0, Object evt) {
						if (evt instanceof FinishEvent) {
							BasicLogger.writeLog(TAG, "Invoking finish");
							finish();
						}
					}
				});
	}

	@Override
	protected void onPause() {
		// XXX Auto-generated method stub
		super.onPause();
		isInFront = false;
	}

	@Override
	protected void onDestroy() {
		// XXX Auto-generated method stub
		super.onDestroy();
	}

	@Override
	protected void onResume() {
		super.onResume();
		// AndroidApplicationContext.getInstance().replaceApplicationContext(this);
		checkModels();
		// registerListerners();
		onVisible();
		isInFront = true;
	}

	public abstract void onStarted();

	@Override
	public void init() {
		AndroidApplicationContext.getInstance().replaceApplicationContext(this);		
		Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

			@Override
			public void uncaughtException(Thread thread, Throwable ex) {
				BasicLogger.getLog().error("FROM UNCAUGHT EXCEPTION HANDLER", new Exception(ex));

			}
		});
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		Map<String, Object> map = AndroidModelContainer.getInstance()
				.getAllModels();
		Set<String> keys = map.keySet();
		outState.putSerializable("keys", new ArrayList<String>(keys));
		BasicLogger.writeLog(TAG, "Saving model state");
		for (String key : map.keySet()) {
			Object model = map.get(key);
			if (model instanceof Serializable) {
				
				outState.putSerializable(key, (Serializable) model);
			} else {
				BasicLogger.writeLog(TAG,
						"Model state not saved because it is not Serializable: "
								+ key);
			}
		}

		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		List<String> keys = (List<String>) savedInstanceState
				.getSerializable("keys");
		for (String key : keys) {
			Serializable model = savedInstanceState.getSerializable(key);
			AndroidModelContainer.getInstance().putModel(key, model);
		}
		super.onRestoreInstanceState(savedInstanceState);
	}

	public boolean isInFront() {
		return isInFront;
	}

	public void setInFront(boolean isInFront) {
		this.isInFront = isInFront;
	}

}
